import { chManager, SourceType, SumType } from './defaultconfig.js';
import {
    ChannelManager,
    ChannelModel, PassModel,
    PassType,
    SignModel
} from './model.js';
import { SendType, toBytesList } from './send_manager.js';
Object.assign(SignModel.prototype, {
    reset() {
        this.freq = parseInt(this.name);
        this.gain = 0;
        this.q = 7.2;
    },
});

Object.assign(PassModel.prototype, {
    reset() {
        this.freq = this.is_high ? this.min_freq : this.max_freq;
        this.type_index = 0;
        this.type.reset();
    },
});

Object.assign(PassType.prototype, {
    reset() {
        this.slope = this.slopeList[0];
    },
});

Object.assign(ChannelModel.prototype, {
    reset() {
        this.mute = false;
        this.phase = false;
        this.db = 0;
        this.delay = 0;
        this.high_pass.reset();
        this.low_pass.reset();
        this.sign_list.forEach(($0) => $0.reset());
    },
    toHex() {
        var list = [];
        //eq
        this.sign_list.forEach(($0, i) => {
            const bytes = toBytesList(SendType.EQ, { ch: this, sign: $0 });
            list.push(bytes);
        });

        //正反向
        const phase_bytes = toBytesList(SendType.PHASE, { ch: this });
        list.push(phase_bytes);

        //通道延迟
        const delay_bytes = toBytesList(SendType.DELAY, { ch: this });
        list.push(delay_bytes);

        //通道静音,db音量
        const db_bytes = toBytesList(SendType.DB, { ch: this });
        list.push(db_bytes);

        //高通
        const high_bytes = toBytesList(SendType.PASS_HIGH, { ch: this, pass: this.high_pass });
        list.push(high_bytes);

        //低通
        const low_bytes = toBytesList(SendType.PASS_LOW, { ch: this, pass: this.low_pass });
        list.push(low_bytes);
        return list;
    },

    //指令，转换成模型
    toModel(bytes) {
        if (bytes.slice(0, 3).decimal == SendType.SUM_CUSTOM.decimal) {
            this.toSum(bytes);
        } else {
            switch (bytes.slice(0, 1).decimal) {
                case SendType.EQ.decimal: {
                    this.toEq(bytes);
                    break;
                }
                case SendType.PHASE.decimal: {
                    this.toPhase(bytes);
                    break;
                }
                case SendType.DELAY.decimal: {
                    this.toDelay(bytes);
                    break;
                }
                case SendType.DB.decimal: {
                    this.toDb(bytes);
                    break;
                }
                case SendType.PASS_HIGH.decimal:
                case SendType.PASS_LOW.decimal: {
                    this.toCross(bytes);
                    break;
                }
                default:
                    break;
            }
        }
    },

    toSum(bytes) {
        if (this.target_list.length <= 10) {
            this.target_list = bytes.slice(4, 4 + this.target_list.length).map(($0) => parseInt($0));
        } else {
            const hex_list = bytes.slice(4, 6);
            const bit_list = hex_list.map(($0) => $0.toString(2).padStart(8, '0').split('').reverse()).flat().slice(0, this.target_list.length);
            this.target_list = bit_list.map(($0) => parseInt($0));
            console.log('=================>bit_list', bit_list, this.target_list);
        }
    },
    toEq(bytes) {
        const index = bytes[2];
        const sign_model = this.sign_list[index];
        sign_model.freq = bytes.slice(3, 5).decimal;
        sign_model.q = bytes.slice(5, 7).decimal / 100.0;
        sign_model.gain = bytes.slice(7, 9).decimal / 10.0 - 20.0;
    },
    toPhase(bytes) {
        this.phase = parseInt(bytes[2]) === 0;
    },
    toDelay(bytes) {
        this.delay = parseFloat((parseInt(bytes.slice(2, 4).decimal) / 100.0).toFixed(1));
    },
    toDb(bytes) {
        this.mute = parseInt(bytes[2]) === 1;
        const v = parseInt(bytes.slice(3, 5).decimal);
        this.db = v == 0 ? 0 : v / -10;
    },
    toCross(bytes) {
        const cmd = bytes[0];
        const type = bytes[2];
        const slope = bytes[3];
        const freq = parseInt(bytes.slice(4, 6).decimal);
        setupCross(cmd === SendType.PASS_HIGH.decimal ? this.high_pass : this.low_pass);
        function setupCross(pass) {
            // pass.type.name = chManager.chlist[0].high_pass.types[type].name;
            pass.type_index = type;
            pass.freq = freq;
            if (type == 0x02) {
                switch (slope) {
                    case 0x00:
                        pass.type.slope = 6;
                        break;
                    case 0x01:
                        pass.type.slope = 12;
                        break;
                    case 0x02:
                        pass.type.slope = 24;
                        break;
                    case 0x03:
                        pass.type.slope = 36;
                        break;
                    case 0x04:
                        pass.type.slope = 48;
                        break;
                    default:
                        break;
                }
            } else {
                switch (slope) {
                    case 0x00:
                        pass.type.slope = 6;
                        break;
                    case 0x01:
                        pass.type.slope = 12;
                        break;
                    case 0x02:
                        pass.type.slope = 18;
                        break;
                    case 0x03:
                        pass.type.slope = 24;
                        break;
                    case 0x04:
                        pass.type.slope = 36;
                        break;
                    case 0x05:
                        pass.type.slope = 48;
                        break;
                    default:
                        break;
                }
            }
        }
    }

});

Object.assign(ChannelManager.prototype, {
    reset() {
        this.chlist.forEach((ch) => ch.reset());
        this.mute = false;
    },

    toHex() {
        var list = [];
        this.chlist.forEach((ch) => {
            const ch_bytes = ch.toHex();
            list.push(...ch_bytes);

            ///合频
            if (this.current_source_list.length > 0) {
                const type = this.current_source_list[this.current_source_list.length - 1];
                ///usb | bg | aux 的合频
                if (type === SourceType.aux || type === SourceType.bt || type === SourceType.usb) {
                    const type_bytes = toBytesList(SendType.SUM_USB_BT, { ch: ch });
                    list.push(type_bytes);

                } else if (type === SourceType.optical || type === SourceType.coaxial) {//toslink | cu 的 合频
                    const type_bytes = toBytesList(SendType.SUM_OPTICAL, { ch: ch });
                    list.push(type_bytes);

                } else {//高电平的合频
                    const type_bytes = toBytesList(SendType.SUM_CUSTOM, { ch: ch });
                    list.push(type_bytes);
                }
            }
        });

        ///音源
        if (this.current_source_list.length > 0) {
            ///12进12出，带主从音源，特殊处理
            this.current_source_list.forEach(($0, i) => {
                if (this.chlist[0].target_list.length == 12) {
                    const source_bytes = toBytesList(SendType.SOURCE, { data: [0xC1 + i, $0] })
                    list.push(source_bytes);
                } else {
                    const source_bytes = toBytesList(SendType.SOURCE, { data: $0 })
                    list.push(source_bytes);
                }
            });
            // const type = this.current_source_list[this.current_source_list.length - 1];
            // const source_bytes = toBytesList(SendType.SOURCE, { data: type })
            // list.push(source_bytes);
        }

        ///总音量
        const db_all_bytes = toBytesList(SendType.DB_ALL);
        list.push(db_all_bytes);
        const hex_string = list.map(($0) => {
            return $0.map((e) => e.toString(16).padStart(2, '0').toUpperCase()).join(',');
        }).join('|\n');
        return hex_string;
    },

    toModel(data) {
        if (data === null || data.length === 0) return;
        this.current_source_list = [];
        data.forEach($0 => {
            const bytes = $0.slice(chManager.config.startBytesIndex, $0.length);
            const hex = bytes.map(n => n.toString(16).padStart(2, '0').toUpperCase()).join(', ');
            console.log('============== 拿到的本地byte', hex);
            //第一步，筛选挂在chManager上的属性 
            if (bytes.slice(0, 1).decimal === SendType.DB_ALL.decimal) {
                const v = bytes.slice(2, 4).decimal;
                this.mute = bytes[1] === 0x01;
                this.db = v == 0 ? 0 : v / -10;
            }
            //符合SendType.SOURCE
            else if (SendType.SOURCE.decimal === bytes.slice(0, 2).decimal) {
                ///12进12出，带主从音源，特殊处理
                if (this.chlist[0].target_list.length === 12) {
                    const temp_list = chManager.source_list.filter(item => item === bytes[3]);
                    this.current_source_list.push(...temp_list);
                } else {
                    const temp_list = chManager.source_list.filter(item => item === bytes[2]);
                    this.current_source_list.push(...temp_list);
                }
            }
            //第二步，再筛选挂在chlist上的属性
            else {
                const cmds = [SendType.EQ, SendType.PHASE, SendType.DELAY, SendType.DB, SendType.PASS_HIGH, SendType.PASS_LOW, SendType.SUM_CUSTOM, SendType.SOURCE].map(($0) => $0.decimal);
                var num = null;
                ///符合SendType.SUM_CUSTOM
                if (cmds.includes(bytes.slice(0, 3).decimal)) {
                    num = bytes[3] - 0xC0 - 1;
                }
                ///符合其他单字节的配置
                else if (cmds.includes(bytes[0])) {
                    num = bytes[1] - 0xC0 - 1;
                }
                if (num === null || num >= this.chlist.length || num < 0) return;
                const ch = this.chlist[num];
                if (ch === null) return;
                ch.toModel(bytes);
            }
        });
        ///转换完了，合频模式切换到自定义custom模式，
        this.current_sum = SumType.custom;
    }
});


